繼眾裡尋它後,我們想繼續看是否有各個欄位都符合關鍵字的結果(真命天菜/女神?),這需要根據輸入的資料的陣列大小自動調整輸入的欄位和對應function的數目,而這功能我問Google大神並沒有得到明確的答案,但想想是可以實現的,分成3個部分,分別為生成輸入欄位、比對有輸入值得欄位做filter,以及調整輸入欄位的寬度(如果資料表格會根據內容調整寬度)。
首先我們要修正上次的filterTable這個function,將原本input和table這兩個argument改為,並在function內用getElementById取得HTML上的內容,這樣就不用外面再包一層(原本filterTable_data()是拗口的寫法),第二是再增加一個hold的argument,再原本if (txtValue.indexOf(filter) > -1)的條件中,再增加if (!hold)的條件,當兩個條件都達到時,才會有display = "",這是避免在多個條件時,在其中一個條件達成時,會洗掉其他條件的沒達成(display = "none"):
function filterTable(inputId, tableId, index, hold) {
let input = document.getElementById(inputId);
let table = document.getElementById(tableId);
// Declare variables
let filter, tr, td, i, txtValue;
filter = input.value;
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 1; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[index];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.indexOf(filter) > -1) {
if (!hold) {
tr[i].style.display = "";
}
} else {
tr[i].style.display = "none";
}
}
}
}
接下來是生成輸入欄位,我們可以使用在day2生成表格的做法,而同樣我們會生成表格,並根據原本表格的欄位的寬度寫入屬性,這樣輸入欄位就會對齊(如果原本表格是自動根據內容調整寬度),然後在cell中寫入輸入,如同在單一輸入時的寫法,但要額外帶著欄位標號以做區分。總結,用JavaScript寫表格,用表頭格式(與下放表格的表頭外觀會一致),每個cell()根據資料的表格讀取寬度並填入,cell寫入輸入(我在一開始將固定的文字拆成string1~string5,對應到上方的註解,讓後面loop中的code比較乾淨):
function genTableFilter(outputId, tableId, keyName) {
//<input type="text" id="filterInput_data" onkeyup="filterTable_multi('filterInput_data', 'searchTable_data', 'dataTable', 0)" placeholder="Search ..." class="form-control"/>
const string1 = "<input type=\"text\" id=\"filterInput_";
const string2 = "\" onkeyup=\"filterTable_multi(\'filterInput_";
const string3 = "\', \'";
const string4 = "\', ";
const string5 = ")\" placeholder=\"Search ...\" class=\"form-control\"/>";
let table = document.getElementById(tableId);
td = table.getElementsByTagName("tr")[0].getElementsByTagName("th");
let content = "<thead><tr>";
for (let i = 0; i < td.length; i++) {
//content += "<th>" + cell + "</th>" ;
let cellWidth = table.rows[0].cells[i].offsetWidth;
content += "<th width=" + cellWidth + ">" + string1 + keyName + i;
content += string2 + keyName + i + string3 + outputId + string3 + tableId + string4 + i;
content += string5 + "</th>";
}
content += "</tr></thead>";
document.getElementById(outputId).innerHTML = content;
}
再來是比對有輸入值的欄位做filter,我們邏輯是這樣:如果輸入欄位有修改值(onkeyup觸發),則會依序對所有欄位都讀取值,如果有值(!= "")則做filter(filterTable這個function),而只有第一個hold為false,也就是會將符合條件的display設為"",這樣可以清除之前的設定,而之後的所做filter的hold為true,則不會洗掉前面判斷display = "none"的結果。若loop後hold還是false,表示所有欄位都沒有輸入值,則同樣做一次filter,將所有display = "none"清回display = "",而最後呼叫的adjuctTableWidthByTable則是下一段所要說明調整寬度的function:
function filterTable_multi(inputId, searchId, tableId, index) {
let table = document.getElementById(tableId);
td = table.getElementsByTagName("tr")[0].getElementsByTagName("th");
let hold = false;
for (let i = 0; i < td.length; i++) {
let inputId_other = inputId.replace(/(\d+)$/, i);
if (document.getElementById(inputId_other).value != "") {
filterTable(inputId_other, tableId, i, hold);
hold = true;
}
}
if (!hold) {filterTable(inputId, tableId, index, hold);}
adjuctTableWidthByTable(tableId, searchId);
}
如果資料表格會根據內容調整寬度,則我們在做filter時由於資料變了,則表格的寬度也可能變動,這樣輸入欄位可能會不對齊,這在使用時會有不協調的感覺。我們同樣可以用之前在生成欄位的方式,再用loop依序抓一次資料表格的寬度,然後調整輸入欄位寬度的屬性:
function adjuctTableWidthByTable(refTableId, targetTableId) {
let refTable = document.getElementById(refTableId);
let tarTable = document.getElementById(targetTableId);
td = refTable.getElementsByTagName("tr")[0].getElementsByTagName("th");
for (let i = 0; i < td.length; i++) {
let cellWidth = refTable.rows[0].cells[i].offsetWidth;
//console.log(cellWidth);
tarTable.getElementsByTagName("tr")[0].getElementsByTagName("th")[i].width = cellWidth;
//console.log(tarTable.rows[0].cells[i].offsetWidth);
}
}
最後我以節錄一開始的Bootstrap所附的表格資料做測試,因為資料的內容長度不一致,可以看出第三個調整寬度的功能的結果。
兩欄filter輸入結果:
無符合條件結果:
無輸入條件結果: